package log

import (
	"fmt"
	"strings"
)

type Level int8

const (
	// DebugLevel logs are typically voluminous, and are usually disabled in
	// production.
	DebugLevel Level = iota - 1
	// InfoLevel is the default logging priority.
	InfoLevel
	// WarnLevel logs are more important than Info, but don't need individual
	// human review.
	WarnLevel
	// ErrorLevel logs are high-priority. If an application is running smoothly,
	// it shouldn't generate any error-level logs.
	ErrorLevel
	// DPanicLevel logs are particularly important errors. In development the
	// logger panics after writing the message.
	DPanicLevel
	// PanicLevel logs a message, then panics.
	PanicLevel
	// FatalLevel logs a message, then calls os.Exit(1).
	FatalLevel
)

// String returns a lower-case ASCII representation of the log level.
func (l Level) String() string {
	switch l {
	case DebugLevel:
		return "debug"
	case InfoLevel:
		return "info"
	case WarnLevel:
		return "warn"
	case ErrorLevel:
		return "error"
	case DPanicLevel:
		return "dpanic"
	case PanicLevel:
		return "panic"
	case FatalLevel:
		return "fatal"
	default:
		return fmt.Sprintf("Level(%d)", l)
	}
}

func (l Level) CapitalString() string {
	return strings.ToUpper(l.String())
}

var defaultCfg = &Config{
	level:      InfoLevel,
	withCaller: false,
	withStack:  false,
	file: fileConfig{
		toFile:           false,
		basePath:         "",
		minDiskSpaceSize: 500,
		maxAge:           7,
	},
	ew: []EncodeWriter{NewConsoleEncodeWriter()},
}

type Config struct {
	app        string //the app name
	level      Level  //the min level for output
	withCaller bool   //output the caller file path
	withStack  bool   //output the stack while error level
	file       fileConfig
	ew         []EncodeWriter
}

type fileConfig struct {
	toFile           bool   //save log to file
	basePath         string //the file base path
	minDiskSpaceSize uint64 //MB
	maxAge           int    //day
}
